package tech

import "ssp/set"

type JETech struct {
	lines         []*House
	baseRowNum    int
	baseColNums   []int
	baseCells     []*Cell
	baseCands     set.Set
	targetCells   []*Cell
	targetRowNums []int
	targetColNums []int
}

func (s *Solve) JE(g *Grid) (used bool, results []*Result) {
	for i := range 2 {
		e := newJETech(g.lines[i*9 : i*9+9])
		if ok, rs := e.je(); ok {
			used = true
			results = append(results, rs...)
		}
	}
	return
}

func newJETech(lines []*House) *JETech {
	return &JETech{
		lines: lines,
	}
}

func (e *JETech) je() (used bool, results []*Result) {
	for i, line := range e.lines {
		e.baseRowNum = i
		for _, baseCols := range jeGetBaseCells(line) {
			e.baseColNums = baseCols
			e.baseCells = []*Cell{line.cells[baseCols[0]], line.cells[baseCols[1]]}
			e.baseCands = unionCellCands(e.baseCells)
			for _, targets := range e.jeGetTargetCells() {
				e.targetCells = []*Cell{e.lines[targets[0]].cells[targets[1]],
					e.lines[targets[2]].cells[targets[3]]}
				e.targetRowNums = []int{targets[0], targets[2]}
				e.targetColNums = []int{targets[1], targets[3]}
				if ok, candCellss := e.verifyCrossLines(); ok {
					used = true
					result := new(Result)
					result.addHelpCells(e.baseCells)
					result.addHelpCells(e.targetCells)
					g2 := result.getHelpCandsGroup()
					for i, cand := range e.baseCands.GetList() {
						g2.add(set.NewSet(cand), candCellss[i])
					}
					result.setStrategyName("JE")
					results = append(results, result)
				}
			}
		}
	}
	return
}

func (e *JETech) jeGetTargetCells() (targetRowColNums [][]int) {
	x := e.baseRowNum % 3
	start := e.baseRowNum / 3 * 3
	r1 := (x+1)/3 + start
	r2 := (x+2)/3 + start

	y := e.baseColNums[0] / 3
	c1_start := (y + 1) / 3 * 3
	for i := c1_start; i < c1_start+3; i++ {
		target1 := e.lines[r1].cells[i]
		if target1.solved() || target1.cands.Intersect(e.baseCands).Count() == 0 {
			continue
		}
		componion1 := e.lines[r2].cells[i]
		if !componion1.solved() || componion1.cands.Intersect(e.baseCands).Count() != 0 {
			continue
		}
	}

	return
}

func (e *JETech) verifyCrossLines() (ok bool, candCellss [][]*Cell) {
	return
}
func jeGetBaseCells(line *House) (baseColNumss [][]int) {
	for start := 0; start < 9; start += 3 {
		cols := []int{}
		for i := start; i < start+3; i++ {
			if line.cells[i].solved() {
				cols = append(cols, i)
			}
		}
		if len(cols) < 2 {
			continue
		}
		for _, baseCols := range combine(cols, 2) {
			cands := line.cells[baseCols[0]].cands.Union(line.cells[baseCols[1]].cands)
			if cands.Count() < 3 || cands.Count() > 5 {
				continue
			}
			baseColNumss = append(baseColNumss, baseCols)
		}
	}
	return
}

func jeFindBaseCells(lines []*House, baseRowNum int,
	baseColNums, targetRowNums, targetColNums []int) (used bool, result *Result) {
	baseCells := []*Cell{lines[baseRowNum].cells[baseColNums[0]], lines[baseRowNum].cells[baseColNums[1]]}
	baseCands := unionCellCands(baseCells)
	if baseCands.Count() != 4 {
		return
	}
	t0 := lines[targetRowNums[0]].cells[targetColNums[0]]
	if t0.cands.Intersect(baseCands).Count() == 0 {
		return
	}
	t1 := lines[targetRowNums[1]].cells[targetColNums[1]]
	if t1.cands.Intersect(baseCands).Count() == 0 {
		return
	}
	targetCands := unionCellCands([]*Cell{t0, t1})
	if !targetCands.IsSuperset(baseCands) {
		return
	}
	c0 := lines[targetRowNums[1]].cells[targetColNums[0]]
	if !c0.solved() && c0.cands.Intersect(t0.cands).Count() > 0 {
		return
	}
	c1 := lines[targetRowNums[0]].cells[targetColNums[1]]
	if !c1.solved() && c1.cands.Intersect(t1.cands).Count() > 0 {
		return
	}

	return
}
